package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.*;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;
import static com.tianji.learning.enums.QuestionStatus.UN_CHECK;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 东哥
 * @since 2024-08-25
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final UserClient userClient;
    private final RemarkClient remarkClient;
    private final IInteractionQuestionService questionService;
    /**
     * day7，新增回答或评论接口，实战4
     *
     * @param replyDTO
     */
    @Override
    @Transactional
    public void addReply(ReplyDTO replyDTO) {
        //1、判断replyDTO是否为空
        if(ObjectUtil.isEmpty(replyDTO)){
            throw new BadRequestException("参数不能为空");
        }
        //2、将replyDTO转成InteractionReply
        InteractionReply reply = BeanUtils.toBean(replyDTO, InteractionReply.class);
        //3、填充reply中字段
        reply.setUserId(UserContext.getUser());
        //4、调用新增方法，新增回复
        this.save(reply);
        //5、判断该回复是回答还是评论(是否有上级回答id)
        //5.1、是回答，需更新问题表中最近一次回答id，并是回答次数+1
        if (ObjectUtil.isEmpty(reply.getAnswerId())){
            questionService.lambdaUpdate().eq(InteractionQuestion::getId,reply.getQuestionId())
                    .set(InteractionQuestion::getLatestAnswerId,reply.getId())
                    .setSql("answer_times=answer_times+1")
                    .update();
        }
        //5.2、是评论，需使回复表中对应回答的回复次数+1
        this.lambdaUpdate().eq(InteractionReply::getId,reply.getAnswerId())
                .setSql("reply_times=reply_times+1")
                .update();
        //6、判断是否是学生回复，是则需更新问题表中问题状态为未查看
        if (replyDTO.getIsStudent()){
            questionService.lambdaUpdate().eq(InteractionQuestion::getId,reply.getQuestionId())
                    .set(InteractionQuestion::getStatus,UN_CHECK)
                    .update();
        }
    }

    /**
     * 分页查询回答或评论列表  实战 3
     *
     * @param replyPageQuery
     * @return
     */
    @Override
    public PageDTO<ReplyVO> queryReply(ReplyPageQuery replyPageQuery, boolean isStudent) {
        //1.判断参数条件
        if (ObjectUtil.isEmpty(replyPageQuery.getQuestionId()) &&
                ObjectUtil.isEmpty(replyPageQuery.getAnswerId())) {
            throw new RuntimeException("问题id和回答id不能同时为空");
        }
        //2.分页查询relay表
        //select * from interaction_reply where question_id = 1585089140469317634 and answer_id = 1585178277083951106
        //and user_id = 129 and  hidden = 0 order by create_time desc limit 0,10
        Page<InteractionReply> replyPage = this.lambdaQuery()
                .eq(ObjectUtil.isNotEmpty(replyPageQuery.getQuestionId()), InteractionReply::getQuestionId, replyPageQuery.getQuestionId())
                .eq(InteractionReply::getAnswerId, BooleanUtils.isTrue(ObjectUtil.isEmpty(replyPageQuery.getAnswerId())) ? 0L : replyPageQuery.getAnswerId())
                .eq(isStudent, InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPage(
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)));
        List<InteractionReply> records = replyPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            //2.0查询的分页数据为空，返回一个空集合
            return PageDTO.empty(replyPage);
        }
        //2.1准备收集回答的userId、评论的目标userId
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> targetUserIds = new HashSet<>();
        //2.2收集用户对业务点赞的id
        Set<Long> bizIds = new HashSet<>(records.size());
        for (InteractionReply record : records) {
            if (!isStudent || !record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            targetUserIds.add(record.getTargetUserId());
            bizIds.add(record.getId());
        }
        targetUserIds.remove(0L);
        targetUserIds.remove(null);
        if (targetUserIds.size() > 0) {
            userIds.addAll(targetUserIds);
        }
        //3.查询用户信息、目标用户的信息(回答或评论的id) targetUserName 用 targetUserId查询
        Map<Long, UserDTO> userInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(userIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userInfoMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }
        if (ObjectUtil.isEmpty(userInfoMap)) {
            throw new RuntimeException("用户信息Map出错");
        }
        //4.调用查询点赞状态Feign接口
        Set<Long> likeStatus = remarkClient.isLiked(bizIds);

        //6.遍历分页的结果进行数据分装
        List<ReplyVO> voList = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            //6.1属性拷贝
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);
            //6.2分装当前用户信息
            UserDTO userDTO = userInfoMap.get(record.getUserId());
            //6.3无论是回答还是回复都要分昵称判断是否为回答
            if (!isStudent || !record.getAnonymity()) {
                vo.setUserName(userDTO.getName());
                vo.setUserIcon(userDTO.getIcon());
            }
            //判断为一级评论
            if (record.getTargetReplyId() != null && Objects.equals(record.getTargetReplyId(), record.getAnswerId())) {
                //6.4给目标用户分装昵称
                UserDTO targetUserDTO = userInfoMap.get(record.getTargetUserId());
                vo.setTargetUserName(targetUserDTO.getName());
            }
            //6.5装当目前用户是否点过赞
            if (likeStatus.contains(record.getId()) && ObjectUtil.isNotEmpty(likeStatus)) {
                vo.setLiked(true);
            }
            //6.6将vo添加至volist
            voList.add(vo);
        }
        //7.返回volist
        return PageDTO.of(replyPage, voList);
    }
    /**
     * day7，隐藏或显示互动问题，实战8
     *
     * @param id
     * @param hidden
     */
    @Override
    public void hiddenOrShowQuestion(Long id, Boolean hidden) {
        //根据id修改隐藏状态
        this.lambdaUpdate().eq(InteractionReply::getId,id)
                .set(InteractionReply::getHidden,hidden)
                .update();
    }
}
